package com.ffcs.crmd.tsp.server.jdbc.provider;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;

import com.ffcs.crmd.tsp.server.api.ConnectionProvider;

/**
 * 
 * 功能说明:DBCP连接池
 *
 * @author FFCS-ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class JdbcConnectionProvider implements ConnectionProvider {
    
    /**
     * 驱动
     */
    private String          driver;
    
    /**
     * 连接地址
     */
    private String          url;
    
    /**
     * 用户名
     */
    private String          username;
    
    /**
     * 密码
     */
    private String          password;
    
    /**
     * 验证从连接池取出的连接
     */
    private String          validationQuery               = "select 0 from dual";
    
    /**
     * 同一时间可以从池分配的最多连接数量。设置为0时表示无限制。
     */
    private int             maxActive                     = 50;
    
    /**
     * 池启动时创建的连接数量
     */
    private int             initialSize                   = 10;
    
    /**
     * 池里不会被释放的最多空闲连接数量,设置为0时表示无限制
     */
    private int             maxIdle                       = 20;
    
    /**
     * 在不新建连接的条件下,池中保持空闲的最少连接数
     */
    private int             minIdle                       = 10;
    
    /**
     * 连接池中连接用完时,新的请求等待时间(毫秒),设置为-1表示无限等待
     */
    private long            maxWait                       = 60 * 1000;
    
    /**
     * 每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接
     */
    private long            timeBetweenEvictionRunsMillis = 60 * 1000;
    
    /**
     * 空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止
     */
    private long            minEvictableIdleTimeMillis    = 60 * 1000;
    
    /**
     * 是否定时验证校验空闲连接
     */
    private boolean         testWhileIdle                 = true;
    
    /**
     * 当已被拿出的连接接近最大连接数时，启动该检查
     * 当超过removeAbandonedTimeout没有使用的连接时，则进行回收
     */
    private boolean         removeAbandoned               = true;
    
    /**
     * 超时时间
     */
    private int             removeAbandonedTimeout        = 3 * 60;
    
    /**
     * 关闭abanded连接时是否输出错误日志
     */
    private boolean         logAbandoned                  = true;
    
    /**
     * 去除连接池时是否验证有效
     */
    private boolean         testOnBorrow                  = false;
    
    /**
     * 放回连接池时是否验证有效
     */
    private boolean         testOnReturn                  = false;
    
    /**
     * 数据源
     */
    private BasicDataSource dataSource                    = new BasicDataSource();
    
    
    /**
     * 
     * 功能说明:获取连接池
     * 
     * @author ZHONGFUHUA
     *
     * @Date 2016年3月28日
     *
     */
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    
    /**
     * 
     * 功能说明:关闭连接池
     * 
     * @author ZHONGFUHUA
     *
     * @Date 2016年3月28日
     *
     */
    @Override
    public void shutdown() throws SQLException {
        if (dataSource != null) {
            this.dataSource.close();
        }
    }
    
    /**
     * 
     * 功能说明:启动连接池
     * 
     * @author ZHONGFUHUA
     *
     * @Date 2016年3月28日
     *
     */
    @Override
    public void initialize() throws SQLException {
        dataSource.setUsername(this.getUsername());
        dataSource.setPassword(this.getPassword());
        dataSource.setUrl(this.getUrl());
        dataSource.setDriverClassName(this.getDriver());
        dataSource.setInitialSize(this.getInitialSize());
        dataSource.setMaxActive(this.getMaxActive());
        dataSource.setValidationQuery(this.getValidationQuery());
        dataSource.setMaxIdle(this.getMaxIdle());
        dataSource.setMinIdle(this.getMinIdle());
        dataSource.setTimeBetweenEvictionRunsMillis(this.getTimeBetweenEvictionRunsMillis());
        dataSource.setMinEvictableIdleTimeMillis(this.getMinEvictableIdleTimeMillis());
        dataSource.setTestWhileIdle(this.isTestWhileIdle());
        dataSource.setTestOnBorrow(this.isTestOnBorrow());
        dataSource.setTestOnReturn(this.isTestOnReturn());
        dataSource.setRemoveAbandoned(this.isRemoveAbandoned());
        dataSource.setRemoveAbandonedTimeout(this.getRemoveAbandonedTimeout());
        dataSource.setLogAbandoned(this.isLogAbandoned());
    }
    
    /**
     * 功能说明: 获取驱动
     *
     * @return driver 驱动
     */
    public String getDriver() {
        return driver;
    }
    
    /**
     * 功能说明: 设置驱动
     *
     * @param driver 驱动 
     */
    public void setDriver(String driver) {
        this.driver = driver;
    }
    
    /**
     * 功能说明: 获取连接地址
     *
     * @return url 连接地址
     */
    public String getUrl() {
        return url;
    }
    
    /**
     * 功能说明: 设置连接地址
     *
     * @param url 连接地址 
     */
    public void setUrl(String url) {
        this.url = url;
    }
    
    /**
     * 功能说明: 获取用户名
     *
     * @return username 用户名
     */
    public String getUsername() {
        return username;
    }
    
    /**
     * 功能说明: 设置用户名
     *
     * @param username 用户名 
     */
    public void setUsername(String username) {
        this.username = username;
    }
    
    /**
     * 功能说明: 获取密码
     *
     * @return password 密码
     */
    public String getPassword() {
        return password;
    }
    
    /**
     * 功能说明: 设置密码
     *
     * @param password 密码 
     */
    public void setPassword(String password) {
        this.password = password;
    }
    
    /**
     * 功能说明: 获取验证从连接池取出的连接
     *
     * @return validationQuery 验证从连接池取出的连接
     */
    public String getValidationQuery() {
        return validationQuery;
    }
    
    /**
     * 功能说明: 设置验证从连接池取出的连接
     *
     * @param validationQuery 验证从连接池取出的连接 
     */
    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }
    
    /**
     * 功能说明: 获取同一时间可以从池分配的最多连接数量。设置为0时表示无限制。
     *
     * @return maxActive 同一时间可以从池分配的最多连接数量。设置为0时表示无限制。
     */
    public int getMaxActive() {
        return maxActive;
    }
    
    /**
     * 功能说明: 设置同一时间可以从池分配的最多连接数量。设置为0时表示无限制。
     *
     * @param maxActive 同一时间可以从池分配的最多连接数量。设置为0时表示无限制。 
     */
    public void setMaxActive(int maxActive) {
        this.maxActive = maxActive;
    }
    
    /**
     * 功能说明: 获取池启动时创建的连接数量
     *
     * @return initialSize 池启动时创建的连接数量
     */
    public int getInitialSize() {
        return initialSize;
    }
    
    /**
     * 功能说明: 设置池启动时创建的连接数量
     *
     * @param initialSize 池启动时创建的连接数量 
     */
    public void setInitialSize(int initialSize) {
        this.initialSize = initialSize;
    }
    
    /**
     * 功能说明: 获取池里不会被释放的最多空闲连接数量设置为0时表示无限制
     *
     * @return maxIdle 池里不会被释放的最多空闲连接数量设置为0时表示无限制
     */
    public int getMaxIdle() {
        return maxIdle;
    }
    
    /**
     * 功能说明: 设置池里不会被释放的最多空闲连接数量设置为0时表示无限制
     *
     * @param maxIdle 池里不会被释放的最多空闲连接数量设置为0时表示无限制 
     */
    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }
    
    /**
     * 功能说明: 获取在不新建连接的条件下池中保持空闲的最少连接数
     *
     * @return minIdle 在不新建连接的条件下池中保持空闲的最少连接数
     */
    public int getMinIdle() {
        return minIdle;
    }
    
    /**
     * 功能说明: 设置在不新建连接的条件下池中保持空闲的最少连接数
     *
     * @param minIdle 在不新建连接的条件下池中保持空闲的最少连接数 
     */
    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }
    
    /**
     * 功能说明: 获取连接池中连接用完时新的请求等待时间(毫秒)设置为-1表示无限等待
     *
     * @return maxWait 连接池中连接用完时新的请求等待时间(毫秒)设置为-1表示无限等待
     */
    public long getMaxWait() {
        return maxWait;
    }
    
    /**
     * 功能说明: 设置连接池中连接用完时新的请求等待时间(毫秒)设置为-1表示无限等待
     *
     * @param maxWait 连接池中连接用完时新的请求等待时间(毫秒)设置为-1表示无限等待 
     */
    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }
    
    /**
     * 功能说明: 获取每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接
     *
     * @return timeBetweenEvictionRunsMillis 每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接
     */
    public long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }
    
    /**
     * 功能说明: 设置每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接
     *
     * @param timeBetweenEvictionRunsMillis 每timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接 
     */
    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }
    
    /**
     * 功能说明: 获取空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开直到连接池中的连接数到minIdle为止
     *
     * @return minEvictableIdleTimeMillis 空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开直到连接池中的连接数到minIdle为止
     */
    public long getMinEvictableIdleTimeMillis() {
        return minEvictableIdleTimeMillis;
    }
    
    /**
     * 功能说明: 设置空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开直到连接池中的连接数到minIdle为止
     *
     * @param minEvictableIdleTimeMillis 空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开直到连接池中的连接数到minIdle为止 
     */
    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }
    
    /**
     * 功能说明: 获取是否定时验证校验空闲连接
     *
     * @return testWhileIdle 是否定时验证校验空闲连接
     */
    public boolean isTestWhileIdle() {
        return testWhileIdle;
    }
    
    /**
     * 功能说明: 设置是否定时验证校验空闲连接
     *
     * @param testWhileIdle 是否定时验证校验空闲连接 
     */
    public void setTestWhileIdle(boolean testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }
    
    /**
     * 功能说明: 获取当已被拿出的连接接近最大连接数时，启动该检查当超过removeAbandonedTimeout没有使用的连接时，则进行回收
     *
     * @return removeAbandoned 当已被拿出的连接接近最大连接数时，启动该检查当超过removeAbandonedTimeout没有使用的连接时，则进行回收
     */
    public boolean isRemoveAbandoned() {
        return removeAbandoned;
    }
    
    /**
     * 功能说明: 设置当已被拿出的连接接近最大连接数时，启动该检查当超过removeAbandonedTimeout没有使用的连接时，则进行回收
     *
     * @param removeAbandoned 当已被拿出的连接接近最大连接数时，启动该检查当超过removeAbandonedTimeout没有使用的连接时，则进行回收 
     */
    public void setRemoveAbandoned(boolean removeAbandoned) {
        this.removeAbandoned = removeAbandoned;
    }
    
    /**
     * 功能说明: 获取超时时间
     *
     * @return removeAbandonedTimeout 超时时间
     */
    public int getRemoveAbandonedTimeout() {
        return removeAbandonedTimeout;
    }
    
    /**
     * 功能说明: 设置超时时间
     *
     * @param removeAbandonedTimeout 超时时间 
     */
    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
        this.removeAbandonedTimeout = removeAbandonedTimeout;
    }
    
    /**
     * 功能说明: 获取关闭abanded连接时是否输出错误日志
     *
     * @return logAbandoned 关闭abanded连接时是否输出错误日志
     */
    public boolean isLogAbandoned() {
        return logAbandoned;
    }
    
    /**
     * 功能说明: 设置关闭abanded连接时是否输出错误日志
     *
     * @param logAbandoned 关闭abanded连接时是否输出错误日志 
     */
    public void setLogAbandoned(boolean logAbandoned) {
        this.logAbandoned = logAbandoned;
    }
    
    /**
     * 功能说明: 获取去除连接池时是否验证有效
     *
     * @return testOnBorrow 去除连接池时是否验证有效
     */
    public boolean isTestOnBorrow() {
        return testOnBorrow;
    }
    
    /**
     * 功能说明: 设置去除连接池时是否验证有效
     *
     * @param testOnBorrow 去除连接池时是否验证有效 
     */
    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }
    
    /**
     * 功能说明: 获取放回连接池时是否验证有效
     *
     * @return testOnReturn 放回连接池时是否验证有效
     */
    public boolean isTestOnReturn() {
        return testOnReturn;
    }
    
    /**
     * 功能说明: 设置放回连接池时是否验证有效
     *
     * @param testOnReturn 放回连接池时是否验证有效 
     */
    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }
    
}
